package com.liqi.web.controller.items;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.liqi.common.annotation.Log;
import com.liqi.common.core.controller.BaseController;
import com.liqi.common.core.domain.AjaxResult;
import com.liqi.common.core.domain.R;
import com.liqi.common.core.page.TableDataInfo;
import com.liqi.common.enums.BusinessType;
import com.liqi.common.utils.DateUtils;
import com.liqi.common.utils.StringUtils;
import com.liqi.common.utils.poi.ExcelUtil;
import com.liqi.common.utils.uuid.GenerateCodeUtils;
import com.liqi.device.domain.dto.ExcludeSubjectInfo;
import com.liqi.items.domain.TCfgService;
import com.liqi.items.domain.TCfgSubject;
import com.liqi.items.domain.TRelFormSubject;
import com.liqi.items.domain.TRelServiceSubject;
import com.liqi.items.domain.VO.FormVO;
import com.liqi.items.domain.VO.RelFormVO;
import com.liqi.items.service.ITCfgServiceService;
import com.liqi.items.service.ITCfgSubjectService;
import com.liqi.items.service.ITRelServiceSubjectService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import com.liqi.sms.utils.SmartHttp;
import com.liqi.sms.utils.TokenUtil;
import com.mysql.cj.xdevapi.JsonArray;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

/**
 * 主题Controller
 *
 * @author xiaoli
 * @date 2022-04-07
 */
@Api(tags = "主题管理")
@RestController
@RequestMapping("/items/subject")
public class TCfgSubjectController extends BaseController {
	// 编程式事务
	@Autowired
	private TransactionTemplate transactionTemplate;

	@Autowired
	private ThreadPoolTaskExecutor poolTaskExecutor;
	
	@Autowired
	private ITCfgSubjectService tCfgSubjectService;

	@Autowired
	private ITRelServiceSubjectService tRelServiceSubjectService;

	@Autowired
	private ITCfgServiceService tCfgServiceService;
	@Value("${MiddlePlatform.Url}")
	private String middlePlatformUrl;

	@Value("${MiddlePlatform.TokenUsername}")
	private String tokenUsername;

	@Value("${MiddlePlatform.TokenPassWord}")
	private String tokenPassWord;

	/**
	 * 查询主题列表
	 */
	@PreAuthorize("@ss.hasPermi('items:subject:list')")
	@GetMapping("/list")
	public TableDataInfo list(TCfgSubject tCfgSubject) {

		if ("".equals(tCfgSubject.getBranchCode()) && "".equals(tCfgSubject.getSubjectName())
				&& tCfgSubject.getSubjectCode() == null) {
			tCfgSubject.setSubjectCode(null);
			tCfgSubject.setSubjectName(null);
			tCfgSubject.setParentSubjectCode("0");
		}

		startPage();
		List<TCfgSubject> list = tCfgSubjectService.selectTCfgSubjectList(tCfgSubject);
		return getDataTable(list);
	}

	/**
	 * 查询主题列表 新增下拉使用
	 */
	/* @PreAuthorize("@ss.hasPermi('items:subject:listForSubject')") */
	@GetMapping("/listForSubject")
	public TableDataInfo listForSubject(TCfgSubject tCfgSubject) {
		startPage();
		List<TCfgSubject> list = tCfgSubjectService.selectTCfgSubjectList(tCfgSubject);
		return getDataTable(list);
	}

	/**
	 * 通过网点 查询主题列表
	 */
	/*
	 * @PreAuthorize("@ss.hasPermi('items:subject:selectTCfgSubjectByBranchCode')")
	 */
	@GetMapping("/selectTCfgSubjectByBranchCode")
	public TableDataInfo selectTCfgSubjectByBranchCode(String branchCode,String systemType) {
		startPage();
		List<TCfgSubject> list = tCfgSubjectService.selectTCfgSubjectByBranchCodeAndSystemType(branchCode,systemType);
		return getDataTable(list);
	}

	/**
	 * 通过主题 查询主题关联过的事项列表
	 */
	/* @PreAuthorize("@ss.hasPermi('items:subject:listServiceSubject')") */
	@GetMapping("/listServiceSubject")
	public TableDataInfo listServiceSubject(TCfgSubject tCfgSubject) {
		startPage();
		List<TCfgService> list = tCfgServiceService.selectTCfgServiceByItemCode(tCfgSubject);
		for (TCfgService service : list) {
			String subjectCode = tCfgSubject.getSubjectCode();
			String serviceCode = service.getServiceCode();
			String serviceName = service.getServiceName();
			TRelServiceSubject tRelServiceSubject = new TRelServiceSubject();
			tRelServiceSubject.setSubjectCode(subjectCode);
			tRelServiceSubject.setServiceCode(serviceCode);
			TRelServiceSubject serviceSubject = tRelServiceSubjectService
					.selectTRelServiceSubjectByServiceSubjectCode(tRelServiceSubject);
			if (serviceSubject != null) {
				service.setSort(serviceSubject.getSort());
			}
		}
		return getDataTable(list);
	}

	/**
	 * 通过主题 查询出排除已于当前主题关联的事项列表
	 */
	/* @PreAuthorize("@ss.hasPermi('items:subject:listExcludeSubject')") */
	@GetMapping("/listExcludeSubject")
	public TableDataInfo listExcludeSubject(ExcludeSubjectInfo excludeSubjectInfo) {
		List<TCfgService> list = new ArrayList<>();
		String serviceName = excludeSubjectInfo.getServiceName();
		String subjectCode = excludeSubjectInfo.getSubjectCode();
		String branchCode = excludeSubjectInfo.getBranchCode();
		String deptName = excludeSubjectInfo.getDeptName();
		if (StringUtils.isNotBlank(subjectCode)) {
			// 排除已关联的主题
			startPage();
			list = tCfgServiceService.selectTCfgServiceListExcludeExistItemCode(branchCode, serviceName, subjectCode, deptName);
			return getDataTable(list);
		} else {
			// 没有关联任何主题，全部都遍历出来
			startPage();
			list = tCfgServiceService.selectTCfgServiceList(new TCfgService());
			return getDataTable(list);
		}
	}

	/**
	 * 导出主题列表
	 */
	@PreAuthorize("@ss.hasPermi('items:subject:export')")
	@Log(title = "主题", businessType = BusinessType.EXPORT)
	@PostMapping("/export")
	public void export(HttpServletResponse response, TCfgSubject tCfgSubject) {
		List<TCfgSubject> list = tCfgSubjectService.selectTCfgSubjectList(tCfgSubject);
		// 进行主题排序
		List<TCfgSubject> sortList = new ArrayList<>();
		// 使用递归排序
		subjectSort(sortList,list,"0");
		ExcelUtil<TCfgSubject> util = new ExcelUtil<TCfgSubject>(TCfgSubject.class);
		util.exportExcel(response, sortList, "主题数据");
	}

	// 递归对主题排序
	private void subjectSort(List<TCfgSubject> sortList,List<TCfgSubject> resource,String parentSubjectCode){
		// 拿到父级编码对应的数据
		List<TCfgSubject> collect = resource.stream().filter(m -> parentSubjectCode.equals(m.getParentSubjectCode())).collect(Collectors.toList());
		// > 0则证明这个父级编码对应有子主题
		if ((long) collect.size() > 0) {
			collect.forEach(m -> {
				sortList.add(m);
				subjectSort(sortList, resource, m.getSubjectCode());
			});
		}
	}

	/**
	 * 获取主题详细信息
	 */
	@PreAuthorize("@ss.hasPermi('items:subject:query')")
	@GetMapping(value = "/{id}")
	public AjaxResult getInfo(@PathVariable("id") Long id) {
		return AjaxResult.success(tCfgSubjectService.selectTCfgSubjectById(id));
	}

	/**
	 * 新增主题
	 */
	@PreAuthorize("@ss.hasPermi('items:subject:add')")
	@Log(title = "主题", businessType = BusinessType.INSERT)
	@PostMapping
	public R add(@RequestBody TCfgSubject tCfgSubject) {
		tCfgSubject.setSubjectCode(GenerateCodeUtils.getSequnce());
		if (tCfgSubject.getParentSubjectCode() == null) {
			tCfgSubject.setParentSubjectCode("0");
		}
		tCfgSubject.setCreateBy(getUsername());
		tCfgSubject.setCreateTime(DateUtils.getNowDate());
		tCfgSubject.setUpdateBy(getUsername());
		tCfgSubject.setUpdateTime(DateUtils.getNowDate());
		tCfgSubject.setStatus(0);

		int key = tCfgSubjectService.insertTCfgSubject(tCfgSubject);

		if (key > 0) {
			// 拿到Id返回给前端tCfgSubject.getId();
			return R.ok(tCfgSubject);
		} else {
			return R.fail("新增主题失败");
		}
	}

	/**
	 * 修改主题
	 */
	@PreAuthorize("@ss.hasPermi('items:subject:edit')")
	@Log(title = "主题", businessType = BusinessType.UPDATE)
	@PutMapping
	public AjaxResult edit(@RequestBody TCfgSubject tCfgSubject) {
		tCfgSubject.setUpdateBy(getUsername());
		tCfgSubject.setUpdateTime(DateUtils.getNowDate());
		return toAjax(tCfgSubjectService.updateTCfgSubject(tCfgSubject));
	}

	/**
	 * 修改主题排序
	 */
	@PreAuthorize("@ss.hasPermi('items:subject:updateTCfgSubjectSortWhenSubjectCode')")
	@Log(title = "主题", businessType = BusinessType.UPDATE)
	@PostMapping("/updateTCfgSubjectSortWhenSubjectCode")
	public AjaxResult updateTCfgSubjectSortWhenSubjectCode(@RequestBody TCfgSubject tCfgSubject) {
		return toAjax(tCfgSubjectService.updateTCfgSubjectSortWhenSubjectCode(tCfgSubject));
	}

	/**
	 * 删除主题
	 */
	@PreAuthorize("@ss.hasPermi('items:subject:remove')")
	@Log(title = "主题", businessType = BusinessType.DELETE)
	@DeleteMapping("/{ids}")
	public AjaxResult remove(@PathVariable Long[] ids) {
		int i = 0;
		for (long id : ids) {
			TCfgSubject tCfgSubject = tCfgSubjectService.selectTCfgSubjectById(id);
			if (tCfgSubject.getSubjectCode()!=null) {
				tCfgSubject.setParentSubjectCode(tCfgSubject.getSubjectCode());
				tCfgSubject.setSubjectCode("");
				tCfgSubject.setSubjectName("");
				tCfgSubject.setLinkTo("");
				tCfgSubject.setSubjectLogo("");
			}
			List<TCfgSubject> list = tCfgSubjectService.selectTCfgSubjectList(tCfgSubject);
			List<String> subjectCodes = new ArrayList<>();
			for(TCfgSubject cfgSubject : list) {
				if (cfgSubject != null) {
					cfgSubject.setUpdateBy(getUsername());
					cfgSubject.setUpdateTime(DateUtils.getNowDate());
					cfgSubject.setStatus(1);
					i = tCfgSubjectService.updateTCfgSubject(cfgSubject);
					Map<String, Object> paramsMap = new HashMap<>();
					String serviceCode = cfgSubject.getServiceCode();
					subjectCodes.add(cfgSubject.getSubjectCode());
					paramsMap.put("serviceCode", serviceCode);
					paramsMap.put("subjectCodes", subjectCodes);
					tRelServiceSubjectService.deleteTRelServiceSubjectBySubjectCode(paramsMap);
				}
			}
		}
		return toAjax(i);
	}

	/**
	 * 批量新增主题事项关联
	 */
	@PreAuthorize("@ss.hasPermi('items:subject:batchAddServiceSubject')")
	@PostMapping("/batchAddServiceSubject")
	public AjaxResult batchAddServiceSubject(@RequestBody List<TRelServiceSubject> tRelServiceSubjectList) {
		return toAjax(tRelServiceSubjectService.batchInsertTRelServiceSubject(tRelServiceSubjectList));
	}

	/**
	 * 删除主题事项关联
	 */
	@PreAuthorize("@ss.hasPermi('item:subject:removeServiceSubject')")
	@Log(title = "主题事项关联", businessType = BusinessType.DELETE)
	@DeleteMapping("/removeServiceSubject")
	public AjaxResult removeServiceSubject(@RequestBody List<TRelServiceSubject> tRelServiceSubjectList) {
		return toAjax(tRelServiceSubjectService.batchDeleteTRelServiceSubject(tRelServiceSubjectList));
	}

	/**
	 * 修改主题事项关联
	 */
	@PreAuthorize("@ss.hasPermi('item:subject:editServiceSubject')")
	@Log(title = "主题事项关联", businessType = BusinessType.UPDATE)
	@PostMapping("/editServiceSubject")
	public AjaxResult editServiceSubject(@RequestBody TRelServiceSubject tRelServiceSubject) {
		return toAjax(tRelServiceSubjectService.updateTRelServiceSubject(tRelServiceSubject));
	}

	/**
	 * 通过主题 查询主题关联过的表单列表
	 */
	@ApiOperation("查询主题关联过的表单列表")
	/* @PreAuthorize("@ss.hasPermi('items:subject:listServiceSubject')") */
	@GetMapping("/listFormSubject")
	public TableDataInfo listFormSubject(String subjectCode) {
		startPage();
		List<TRelFormSubject> list = tRelServiceSubjectService.selectTRelFormSubjectByServiceSubjectCode(subjectCode);

		return getDataTable(list);
	}

	/**
	 * 通过主题 查询出排除已于当前主题关联的事项列表
	 */
	@ApiOperation(" 查询出排除已于当前主题关联的事项列表")
	/* @PreAuthorize("@ss.hasPermi('items:subject:listExcludeSubject')") */
	@PostMapping(value = "/listExcludeForm")
	public R listExcludeForm(@RequestBody FormVO formVO) {
		Integer pageNum = (Integer) formVO.getPageNum();
		Integer pageSize = (Integer) formVO.getPageSize();
		String subjectCode = (String) formVO.getSubjectCode();
		String formName = formVO.getFormName() == null ? "" : formVO.getFormName();
		if (null==pageNum && null == pageSize && StringUtils.isBlank(subjectCode)) {
			return R.fail("pageNum,pageSize,subjectCode不能为空！");
		}
		//只查询没有关联的表单
		//formVO.setIsRel("1");
		
		Map<String, String> params = new HashMap<>();
		params.put("pageNum", pageNum.toString());
		params.put("pageSize", pageSize.toString());
		params.put("subjectCode", subjectCode);
		params.put("formName", formName);
		Map<String, String> heardMap = new HashMap<>();
		heardMap.put("Authorization",TokenUtil.getToken(middlePlatformUrl + "auth/token", tokenUsername, tokenPassWord));
		Map<String, Object> resultmap = new HashMap();
		try {
			String json = SmartHttp.sendGet(middlePlatformUrl + "/service/selfService/queryFormList4SelfService", params, heardMap);
			JSONObject repJson = JSONObject.parseObject(json);
	        Integer code = (Integer) repJson.get("code");
	        if (200!=code || repJson.get("data") == null) {
	        	String msg = repJson.get("msg").toString();
				return R.fail(msg);
			}
	        Map rspData = (Map) repJson.get("data");
			if (rspData != null) {
				String aString = rspData.get("rows").toString();
				List<TRelFormSubject> tRelFormSubjectList = JSON.parseArray(aString, TRelFormSubject.class);
				resultmap.put("total", rspData.get("total"));
				resultmap.put("tRelFormSubjectList", tRelFormSubjectList);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return R.ok(resultmap);
	}

	/**
	 * 批量新增主题表单关联
	 */
	@ApiOperation(" 批量新增主题表单关联")
	@PreAuthorize("@ss.hasPermi('items:subject:batchAddServiceSubject')")
	@PostMapping("/batchAddFormSubject")
	public AjaxResult batchAddFormSubject(@RequestBody List<TRelFormSubject> tRelFormSubjectList) {

		// todo 这里要调关联事项
		// 将接收到的远程数据库批量插入本地事项库
		if (!tRelFormSubjectList.isEmpty()) {
			// 事项编码
			List<String> collect = tRelFormSubjectList.stream().map(m -> m.getFormKey()).collect(Collectors.toList());
			List<String> subjectCode = tRelFormSubjectList.stream().map(a -> a.getSubjectCode()).collect(Collectors.toList());
			transactionTemplate.executeWithoutResult(new Consumer<TransactionStatus>() {
				@Override
				public void accept(TransactionStatus transactionStatus) {
					for (TRelFormSubject tRelFormSubject :tRelFormSubjectList) {{
							// 先将每个远程事项库的事项插入本地数据库表
						// 先将每个远程事项库的事项插入本地数据库表
						tRelFormSubject.setCreateBy(getUsername());
						tRelFormSubject.setCreateTime(DateUtils.getNowDate());
						tRelFormSubject.setStatus(0);
						tRelServiceSubjectService.batchInsertTRelFormSubject(tRelFormSubject);						
						}
					}
				}
			});
			
			// 这里使用异步调用中台
			Map<String, String> heardMap = new HashMap<>();
			heardMap.put("Authorization", TokenUtil.getToken(middlePlatformUrl + "auth/token", tokenUsername, tokenPassWord));			
			(subjectCode).forEach(a ->{
			(collect).forEach(m ->{
				CompletableFuture.runAsync(() -> { HashMap<String, String> hashMap = new HashMap<>();
				hashMap.put("relFlag", "1");
				hashMap.put("FormKey", m);
				hashMap.put("subjectCode", a);
				String json = JSON.toJSONString(hashMap);
				try {
					String body = SmartHttp.sendPostJson(middlePlatformUrl + "service/selfService/relForm",json, heardMap);
				} catch (Exception e) {
					logger.error("与中台关联事项出错::事项编码为:{}",m);
					e.printStackTrace();
				}
				}, poolTaskExecutor);
			});
			});
			return AjaxResult.success("批量添加完成");
		} else {
			return AjaxResult.error("请勾选相对应的远程事项进行添加");
		}
	
		//return toAjax(tRelServiceSubjectService.batchInsertTRelFormSubject(tRelFormSubjectList));
	}

	/**
	 * 删除主题表单关联
	 */
	@ApiOperation(" 删除主题表单关联")
//    @PreAuthorize("@ss.hasPermi('item:subject:removeServiceSubject')")
//    @Log(title = "主题事项关联", businessType = BusinessType.DELETE)
	@DeleteMapping("/removeFormSubject/{ids}")
	@Transactional
	public AjaxResult removeFormSubject(@PathVariable Long[] ids) {
		tRelServiceSubjectService.batchDeleteTRelFormSubject(ids);
		// 调用中台解除关联事项
		List<String> fromKeys = tRelServiceSubjectService.getFormKeyByIds(ids);
		Map<String, String> heardMap = new HashMap<>();
		heardMap.put("Authorization", TokenUtil.getToken(middlePlatformUrl + "auth/token", tokenUsername, tokenPassWord));
		fromKeys.forEach(m ->{
			Map<String, String> hashMap = new HashMap<>();
			hashMap.put("relFlag", "2");
			hashMap.put("formKey", m);
			hashMap.put("subjectCode", m);
			String json = JSON.toJSONString(hashMap);
			try {
				String body = SmartHttp.sendPostJson(middlePlatformUrl + "service/selfService/relForm", json, heardMap);
				JSONObject jsonObject = JSON.parseObject(body);
				if ((Integer)jsonObject.get("code") != 200){
					throw new RuntimeException("调用中台出错。关联失败");
				}
			} catch (Exception e) {
				e.printStackTrace();
				throw new RuntimeException(e.getMessage());
			}
		});
		return AjaxResult.success();
	}

	/**
	 * 修改主题表单关联
	 */
	@ApiOperation("修改主题表单关联")
	// @PreAuthorize("@ss.hasPermi('monitor:faultlog:edit')")
	@PutMapping("/updateFormSubject")
	public AjaxResult edit(@RequestBody TRelFormSubject tRelFormSubjectList) {
		return toAjax(tRelServiceSubjectService.updateTRelFormSubject(tRelFormSubjectList));
	}
	
	

//	/**
//	 * 自助服务关联或取消关联表单
//	 */
//	@ApiOperation(" 自助服务关联或取消关联表单")
//	@RequestMapping(value = "/relForm", method = RequestMethod.POST)
//	public R relForm(@RequestBody List<RelFormVO> relFormVO) {
//		Map<String, Object> resultmap = new HashMap();
//		RelFormVO rVo = new RelFormVO();
//		for (RelFormVO rel : relFormVO) {
//			String relFlag = rel.getRelFlag();
//			String formKey = rel.getFormKey();
//			String subjectCode = rel.getSubjectCode();
//			if (StringUtils.isBlank(relFlag) && StringUtils.isBlank(formKey)
//			&& StringUtils.isBlank(subjectCode)) {
//				return R.fail("formKey,relFlag,subjectCode不能为空！");
//			}else {
//				rVo.setFormKey(formKey);
//				rVo.setRelFlag(relFlag);
//				rVo.setSubjectCode(subjectCode);
//			}		
//        JSONObject reqJson = (JSONObject) JSONObject.toJSON(rVo);
//		Map<String, String> heardMap = new HashMap<>();
//		heardMap.put("Authorization",
//				TokenUtil.getToken(middlePlatformUrl + "auth/token", tokenUsername, tokenPassWord));		
//		try {
//			String json = SmartHttp.sendPostJson(middlePlatformUrl + "service/selfService/relForm", reqJson.toString(), heardMap);
//			JSONObject repJson = JSONObject.parseObject(json);
//	        Integer code = (Integer) repJson.get("code");
//	        String msg = repJson.get("msg").toString();
//	        if (200!=code) {
//				return R.fail(msg);
//			}
//			String rspData = repJson.get("data").toString();
//			String data = rspData == null ? null : rspData;
//			resultmap.put("data", data);
//		
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
//		}
//		
//		return R.ok(resultmap);		
//	}
}
